Celem jest uzyskanie wymienności metod
o wspólnej sygnaturze.

W tym celu tworzymy interfejs {\tt Strategia},
w którym określamy nagłówki metod.

Następnie tworzymy konkretne klasy
implementujące te metody.

Kontekst posiada zmienną typu {\tt Strategia}.
W czasie wykonywania przypisywana jest do niej
konkretna strategia. 

{\small {\bf Uwaga.} W cytowanym kodzie dla uproszczenia pomijam \#define, \#include, using.}

\paragraph{Kontekst i interfejs.}
Kontekst wyboru strategii stanowi
klasa {\tt Pracownik}, w której będę korzystał z metod
\begin{itemize}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
\item {\tt string getGdziePracuje()}, która zwraca miejsce pracy 
\item {\tt string getCzymDojezdza()}, która zwraca środek transportu
\end{itemize}
Różni pracownicy będą mieli różne implementacje tych metod.
Podczas wywołania konstruktora będzie podejmowana decyzja o wyborze.

Metodę {\tt getGdziePracuje()} umieszczam w interfejsie
{\tt IPracowac}.
\begin{lstCpp}
class IPracowac {
public:
    virtual std::string getGdziePracuje() = 0;
};
\end{lstCpp}

Metodę {\tt getCzymDojezdza()} umieszczam w interfejsie
{\tt IDojezdzac}.
\begin{lstCpp}
class IDojezdzac {
public:
    virtual std::string getCzymDojezdza() = 0;
};
\end{lstCpp}

Kontekst stanowi klasa pracownika.
\begin{lstCpp}
class Pracownik {
private:
    string nazwa;
    IPracowac* pracowac;   /**< dowolna implementacja IPracowac  */
    IDojezdzac* dojezdzac; /**< dowolna implementacja IDojezdzac */
public:
    Pracownik(string zawod);
    ~Pracownik();
    friend ostream& operator<< (ostream& os, const Pracownik& p);   
};
\end{lstCpp}

\paragraph{Implementacje.}
Tworzę pierwsze implementacje obu strategii oraz Pracownika.

Dla pracowników przychodni tworzę klasę
\begin{lstCpp}
class Przychodnia : public IPracowac {
public:
    std::string getGdziePracuje() { return "w przychodni"; }
};
\end{lstCpp}

Dla pracowników dojeżdżających samochodem tworzę klasę
\begin{lstCpp}
class Przychodnia : public IPracowac {
public:
    std::string getGdziePracuje() { return "w przychodni"; }
};
\end{lstCpp}

Implementacja metod klasy {\tt Pracownik}.
\begin{lstCpp}
Pracownik::Pracownik(string zawod) : nazwa(zawod) {
    if(zawod=="lekarz") {
        pracowac = new Przychodnia();
        dojezdzac = new Samochod();
    } else {
        throw "nieznany zawod";
    }
}

Pracownik::~Pracownik() {
    if(pracowac) {
        delete pracowac;
    }
    if(dojezdzac) {
        delete dojezdzac;
    }
}

ostream& operator<< (ostream& os, const Pracownik& p) {
    // wywoluje metode z interfejsu
    return os << p.nazwa << " pracuje " << p.pracowac->getGdziePracuje() 
              <<", do pracy dojezdza " << p.dojezdzac->getCzymDojezdza() 
              << endl;
}
\end{lstCpp}

Główna funkcja programu.
\begin{lstCpp}
int main(int argc, char** argv) {
    string z;
    cout << "Podaj zawod: "; cin >> z;
    while(z!="q" && z!="Q") {
        try {
            Pracownik *p1 = new Pracownik(z);
            cout << *p1 << endl;
        } catch (const char* wyjatek) {
            cout << wyjatek << endl;
        }
        cout << "Podaj zawod: "; cin >> z;
    }
    return 0;
}
\end{lstCpp}
Uruchomienie.
\begin{lstV}
Podaj zawod: lekarz
lekarz pracuje w przychodni, do pracy dojezdza samochodem

Podaj zawod: nauczyciel
nieznany zawod
Podaj zawod: q
\end{lstV}


\paragraph{Dodanie drugiej strategii.}
Załóżmy, że chce dodać konkretną strategię pracy w szkole
oraz konkretną strategię dojazdu do pracy autobusem.
Tworzę klasę {\tt Szkola} implementującą interfejs {\tt IPracowac}.
\begin{lstCpp}
class Szkola : public IPracowac {
public:
    std::string getGdziePracuje() { return "w szkole"; }
};
\end{lstCpp}
oraz  klasę {\tt Autobus} implementującą interfejs {\tt IDojezdzac}.
\begin{lstCpp}
class Autobus : public IDojezdzac {
public:
    std::string getCzymDojezdza() { return "autobusem"; }
};
\end{lstCpp}

Jedyne zmiany to dołączenie klas  w kontekście
\begin{lstCpp}
#include "Pracownik.h"
#include "Przychodnia.h"
#include "Szkola.h"
#include "Samochod.h"
#include "Autobus.h"


Pracownik::Pracownik(string zawod) : nazwa(zawod) {
    if(zawod=="lekarz") {
        pracowac = new Przychodnia();
        dojezdzac = new Samochod();
    } else if (zawod=="pielegniarka") {
        pracowac = new Przychodnia();
        dojezdzac = new Autobus();
    } else if (zawod=="nauczyciel") {
        pracowac = new Szkola();
        dojezdzac = new Autobus();
    } else {
        throw "nieznany zawod";
    }
}
\end{lstCpp}
Cała reszta programu: inne metody pracownika,
inne interfejsy, funkcja {\tt main()} nie wymagają zmian.


%Zmianymożna
%sprawdzić {\tt git diff}, jeżeli wersje zapisano w różnych commitach.
% {\small
%\begin{lstV}
% git log --pretty=oneline --abbrev-commit --all --graph -3
%* 685228d Wzorzec strategia: kolejne implementacje
%* b174726 Wzorzec strategia: pierwsza implementacja: lekarz
%* b9e7d16 Observer: poprawki w opisie (tex)
%
%git diff b174 6852 cpp/algorytm/wzorce/strategia-1/Pracownik.cpp
%\end{lstV}
%}

\paragraph{Podsumowanie.}
%Przejrzyjmy zmiany w kodzie głównego pliku,
%gdy dodaję nową strategię.
%\begin{itemize}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
%\item
%Usuwam instancję drugiego  obserwatora.
%\begin{lstCpp}
%delete mRozkurcz;
%\end{lstCpp}
%\end{itemize}
Zalety
\begin{enumerate}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
\item Dodawanie nowej klasy sprowadza się do stworzenia nowej klasy
 implementującej strategię. 
 \item Zmianie nie ulega metoda korzystająca z interfejsu (tutaj \verb+operator<<()+)
\end{enumerate}

%\includegraphics[scale=0.7]{rys/algorytm-wzorce-observer-1}
